package parser.nodes;

import codegen.CodeGen;
import codegen.ParamDescr;
import codegen.ProcedureDescr;
import codegen.VarDescr;
import scanner.Token;

//ProcedureDeclaration = ProcedureHeading ';' ProcedureBody ident
public class ProcedureDeclarationNode extends Node {
    private ProcedureHeadingNode signature;
    private ProcedureBodyNode body;

    public ProcedureDeclarationNode(ProcedureHeadingNode signature, ProcedureBodyNode body) {
        this.signature = signature;
        this.body = body;
    }
    
    @Override
    public void print() {
        p("ProcedureDeclaration:");
        indent();
        signature.print();
        p(";");
        body.print();
        p(signature.getProcName());
        unindent();
    }

    public ProcedureHeadingNode getSignature() {
        return signature;
    }

    @Override
    public void abstractPrint() {
        p("PROCDECL");
        indent();
        signature.abstractPrint();
        body.abstractPrint();
        unindent();
    }

	@Override
	public void compile(CodeGen c) throws CompileError {
		c.levelUp();
		//Deskriptor der Prozedur holen
		ProcedureDescr proc = (ProcedureDescr)c.findDescr(signature.getProcName().toString()); 
		
		//Parameterliste in die Symboltabelle laden
		for (ParamDescr param : proc.getParams())
			c.putDescr(param.getName(), param);
		//Rest abarbeiten
		c.outstr("//Anfang Prozedur " + proc.getName());
		c.outstr("LABEL, " + proc.getStart());
		
		c.outstr("INIT, 2");
		c.outstr("PUSHREG, RK");
		c.outstr("PUSHI, " + c.getLevel());
		c.outstr("PUSHREG, SL");
		c.outstr("GETSP");
		c.outstr("PUSHI, " + c.getLevel());
		c.outstr("SETSL");
		body.compile(c);
		c.outstr("PUSHI, " + c.getLevel());
		c.outstr("POPREG, SL");
		c.outstr("POPREG, RK");
		c.outstr("REDUCE, 2");
		c.outstr("RET");
		c.outstr("//Ende Prozedur " + proc.getName());
		
		c.levelDown();
	}
}
